//
//  UIViewController+HBCategory.m
//  HBLibary
//
//  Created by Rambo on 2018/10/27.
//

#import "UIViewController+HBCategory.h"
#import "NSObject+HBCategory.h"
#import <objc/runtime.h>

@interface UIViewController ()

@property (nonatomic, assign) BOOL hb_viewControllerIsShowing;

@end

@implementation UIViewController (HBCategory)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [NSObject hb_swizzlingInstanceMethodWithClass:self originSel:@selector(viewDidLoad) newSel:@selector(UIViewController_HBCategory_viewDidLoad)];
        
        [NSObject hb_swizzlingInstanceMethodWithClass:self originSel:@selector(viewDidAppear:) newSel:@selector(UIViewController_HBCategory_viewDidAppear:)];
        
        [NSObject hb_swizzlingInstanceMethodWithClass:self originSel:@selector(viewDidDisappear:) newSel:@selector(UIViewController_HBCategory_viewDidDisappear:)];
    });
}

+ (instancetype)hb_currentViewController{
    // Find best view controller
    UIViewController *viewController = [[[UIApplication sharedApplication] delegate] window].rootViewController;
    return [UIViewController hb_findBestViewController:viewController];
}

+ (UIViewController *)hb_findBestViewController:(UIViewController*)vc{
    if (vc.presentedViewController) {
        // Return presented view controller
        return [UIViewController hb_findBestViewController:vc.presentedViewController];
    } else if ([vc isKindOfClass:[UISplitViewController class]]) {
        // Return right hand side
        UISplitViewController *svc = (UISplitViewController *)vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController hb_findBestViewController:svc.viewControllers.lastObject];
        else
            return vc;
    } else if ([vc isKindOfClass:[UINavigationController class]]) {
        // Return top view
        UINavigationController *svc = (UINavigationController *) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController hb_findBestViewController:svc.topViewController];
        else
            return vc;
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        // Return visible view
        UITabBarController *svc = (UITabBarController *) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController hb_findBestViewController:svc.selectedViewController];
        else
            return vc;
    } else {
        // Unknown view controller type, return last child view controller
        return vc;
    }
}

- (void)UIViewController_HBCategory_viewDidLoad{
    [self UIViewController_HBCategory_viewDidLoad];
    if (self.navigationController) {
        [self.navigationController.interactivePopGestureRecognizer addTarget:self action:@selector(hb_handleInteractivePopGestureRecognizer:)];
    }
}


- (void)UIViewController_HBCategory_viewDidAppear:(BOOL)animated{
    [self UIViewController_HBCategory_viewDidAppear:animated];
    self.hb_viewControllerIsShowing = YES;
}

- (void)UIViewController_HBCategory_viewDidDisappear:(BOOL)animated{
    [self UIViewController_HBCategory_viewDidDisappear:animated];
    self.hb_viewControllerIsShowing = NO;
}

- (void)hb_handleInteractivePopGestureRecognizer:(UIScreenEdgePanGestureRecognizer*)gestureRecognizer {
    if (!self.hb_viewControllerIsShowing) return;
    if (self.hb_panBlock) {
        self.hb_panBlock([gestureRecognizer translationInView:self.view].x, gestureRecognizer);
    }
}

- (void)setHb_panBlock:(UIViewControllerPanBlock)hb_panBlock{
    objc_setAssociatedObject(self, @selector(hb_panBlock), hb_panBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (UIViewControllerPanBlock)hb_panBlock{
    return objc_getAssociatedObject(self, @selector(hb_panBlock));
}

- (void)setHb_viewControllerIsShowing:(BOOL)hb_viewControllerIsShowing{
    objc_setAssociatedObject(self, @selector(hb_viewControllerIsShowing), @(hb_viewControllerIsShowing), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)hb_viewControllerIsShowing{
    return [objc_getAssociatedObject(self, @selector(hb_viewControllerIsShowing)) boolValue];
}

@end
